﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Collections.Generic;
using System.IO;
using System.Xml.Linq;
using System.Collections.ObjectModel;
using System.Windows.Controls.Primitives;
using System.Linq;
using System.Net.NetworkInformation;
using System.ComponentModel;
using System.Xml.Serialization;
using System.Xml;
using Nok_Air.NokObjects;

namespace Nok_Air.WebService
{
    public class NokAirServicesHelper
    {
        private string origin, destination, departureDay, departureMonth, departureYear, roundtripFlag, numseat;
        private DateTime departureDateTime, returnDateTime;
        private ObservableCollection<NokObjects.AirportItem> tmpAirportItem;
        private ObservableCollection<NokObjects.ScheduleItemViewModel> tmpSchedulItem;
        private ObservableCollection<AvailabilityItemViewModel> tmpFlightSegments;
        private string SubmitID;
        private string lastnamePar;
        //for check what pasenger had checked in
        private int indexFlight;

        byte[] data;

        // Constructor
        public NokAirServicesHelper()
        {
            origin = null; destination = null; departureDay = null; departureMonth = null; departureYear = null; roundtripFlag = null; numseat = null;
            departureDateTime = new DateTime(); returnDateTime = new DateTime();
            tmpAirportItem = new ObservableCollection<NokObjects.AirportItem>();
            tmpSchedulItem = new ObservableCollection<NokObjects.ScheduleItemViewModel>();
            tmpFlightSegments = new ObservableCollection<AvailabilityItemViewModel>();
            lastnamePar = "";
            indexFlight = -1;
        }

        private T Deserialize<T>(XElement xmlElement, XmlRootAttribute xRoot)
        {
            XmlSerializer xs = new XmlSerializer(typeof(T), xRoot);
            XmlReader xr = xmlElement.CreateReader();
            return (T)xs.Deserialize(xr);
        }

        private enum NokAirServicesMode
        {
            GetAvailableAirports,
            GetDestinations,
            GetSchedule,
            GetBookingByBookingNumber,
            GetInventoryDate,
            GetAvailability,
            GetFees,
            SubmitBookingV2,
            GetSubmitBookingStatus,
            PricingV2,
            GetSeats,
            CheckIn,
            GetPassengers,
            RegisterPaymentChannel
        };
        private void CallWebService(NokAirServicesMode mode, params object[] args)
        {
            string xmlns = "http://www.nokair.com/webservices/";
            Uri ws_endpoint = new Uri("http://dev.nokair.com:8080/webServices/services.asmx");
            string username = "winsphone";
            string password = "Nokfly2005";
            string soapbody = "";
            string action = "";
            EventHandler<RequestCompletedEventArgs> completed = null;
            switch (mode)
            {
                #region GetAvailableAirports
                case NokAirServicesMode.GetAvailableAirports:
                    action = "http://www.nokair.com/webservices/GetAvailableAirports";
                    soapbody = "<GetAvailableAirports xmlns='http://www.nokair.com/webservices/' />";
                    completed = GetAvailableAirport_Completed;
                    break;
                #endregion
                #region GetDestinations
                case NokAirServicesMode.GetDestinations:
                    action = "http://www.nokair.com/webservices/GetDestinations";
                    soapbody = "<GetDestinations xmlns='http://www.nokair.com/webservices/'> <Origin>{0}</Origin> </GetDestinations>";
                    soapbody = string.Format(soapbody, args[0]);
                    completed = GetDestinations_Completed;
                    break;
                #endregion
                #region GetSchedule
                case NokAirServicesMode.GetSchedule:
                    action = "http://www.nokair.com/webservices/GetSchedule";
                    soapbody = "<GetSchedule xmlns='http://www.nokair.com/webservices/'>"
                        + "<origin>{0}</origin><destination>{1}</destination><departureDate>{2}</departureDate></GetSchedule>";
                    soapbody = string.Format(soapbody, origin, destination, departureMonth + "/" + departureDay + "/" + departureYear);
                    completed = GetSchedule_Completed;
                    break;
                #endregion
                #region GetBookingByBookingNumber
                case NokAirServicesMode.GetBookingByBookingNumber:
                    action = "http://www.nokair.com/webservices/GetBookingByNumber";
                    soapbody = "<GetBookingByNumber xmlns='http://www.nokair.com/webservices/'>"
                        + "<booking_number>{0}</booking_number><lastName>{1}</lastName></GetBookingByNumber>";
                    soapbody = string.Format(soapbody, args[0], args[1]);
                    completed = GetBookingByBookingNumber_Completed;
                    break;
                #endregion
                #region GetInventoryDate
                case NokAirServicesMode.GetInventoryDate:
                    action = "http://www.nokair.com/webservices/GetInventoryDate";
                    soapbody = "<GetInventoryDate xmlns='http://www.nokair.com/webservices/' />";
                    completed = GetInventoryDate_Completed;
                    break;
                #endregion
                #region GetAvailability
                case NokAirServicesMode.GetAvailability:
                    action = "http://www.nokair.com/webservices/GetAvailability";
                    soapbody = "<GetAvailability xmlns='http://www.nokair.com/webservices/'>"
                        + "<DepartureAirport>{0}</DepartureAirport><ArrivalAirport>{1}</ArrivalAirport>"
                        + "<BoardDate>{2}</BoardDate><ReturnDate>{3}</ReturnDate>"
                        + "<NumberOfSeats>{4}</NumberOfSeats>"
                        + "<RoundTripFlag>{5}</RoundTripFlag>"
                        + "<AgencyCode>00000001</AgencyCode>"
                        + "<Currency>THB</Currency></GetAvailability>";
                    soapbody = string.Format(
                        soapbody,
                        origin,
                        destination,
                        String.Format("{0:MM}", departureDateTime) + "/" + String.Format("{0:dd}", departureDateTime) + "/" + String.Format("{0:yyyy}", departureDateTime),
                        String.Format("{0:MM}", returnDateTime) + "/" + String.Format("{0:dd}", returnDateTime) + "/" + String.Format("{0:yyyy}", returnDateTime),
                        numseat,
                        roundtripFlag
                    );
                    completed = GetAvailability_Completed;
                    break;
                #endregion
                #region GetFees
                case NokAirServicesMode.GetFees:
                    action = "http://www.nokair.com/webservices/GetFees";
                    soapbody = "<GetFees xmlns='http://www.nokair.com/webservices/' />";
                    completed = GetFees_Completed;
                    break;
                #endregion
                #region PricingV2
                case NokAirServicesMode.PricingV2:
                    action = "http://www.nokair.com/webservices/PricingV2";
                    soapbody = "<PricingV2 xmlns='http://www.nokair.com/webservices/'>{0}</PricingV2>";
                    soapbody = string.Format(soapbody, args[0]);
                    completed = PricingV2_Completed;
                    break;
                #endregion
                #region SubmitBookingV2
                case NokAirServicesMode.SubmitBookingV2:
                    action = "http://www.nokair.com/webservices/SubmitBookingV2";
                    soapbody = "<SubmitBookingV2 xmlns='http://www.nokair.com/webservices/'>"
                       + "<PricingId>{0}</PricingId>"
                       + "{1}" // Flight XML string
                       + "<passengers>{2}</passengers>"
                       + "<payment><DocumentNo/><PaymentType>{3}</PaymentType><Amount>{4}</Amount><Currency>THB</Currency></payment>"
                       + "<contact>{5}</contact>"
                       + "<RegisterId>{6}</RegisterId>"
                       + "</SubmitBookingV2>";
                    soapbody = string.Format(soapbody, args[0], args[1], args[2], args[3], args[4], args[5], args[6]);
                    completed = SubmitBookingV2_Completed;
                    break;
                #endregion
                #region GetSubmitBookingStatus
                case NokAirServicesMode.GetSubmitBookingStatus:
                    action = "http://www.nokair.com/webservices/GetSubmitBookingStatus";
                    soapbody = "<GetSubmitBookingStatus xmlns='http://www.nokair.com/webservices/'><SubmitID>{0}</SubmitID></GetSubmitBookingStatus>";
                    soapbody = string.Format(soapbody, args[0]);
                    completed = GetSubmitBookingStatus_Completed;
                    break;
                #endregion
                #region GetSeats
                case NokAirServicesMode.GetSeats:
                    action = "http://tempuri.org/GetSeats";
                    soapbody = " <GetSeats xmlns='http://tempuri.org/'>"
                        + "<FlightNo>{0}</FlightNo>"
                        + "<FlightDate>{1}</FlightDate>"
                        + "<Bookingno>{2}</Bookingno>"
                        + "<ClassCode>{3}</ClassCode>"
                        + "</GetSeats>";
                    soapbody = string.Format(soapbody, args[0], args[1], args[2], args[3]);
                    username = "NokWin";
                    password = "NokTest2011";
                    xmlns = "http://tempuri.org/";
                    completed = GetSeats_Completed;
                    ws_endpoint = new Uri("http://dev.nokair.com:8080/NokCheckinService/Service.asmx");
                    break;
                #endregion
                #region CheckIn
                case NokAirServicesMode.CheckIn:
                    action = "http://tempuri.org/CheckIn";
                    soapbody = "<CheckIn xmlns='http://tempuri.org/'><paxs>{0}</paxs></CheckIn>";
                    soapbody = string.Format(soapbody, args[0]);
                    username = "NokWin";
                    password = "NokTest2011";
                    xmlns = "http://tempuri.org/";
                    completed = CheckIn_Completed;
                    ws_endpoint = new Uri("http://dev.nokair.com:8080/NokCheckinService/Service.asmx");
                    break;
                #endregion
                #region GetPassengers
                case NokAirServicesMode.GetPassengers:
                    action = "http://tempuri.org/GetPassengers";
                    soapbody = " <GetPassengers xmlns='http://tempuri.org/'>"
                            + "<BookingNo>{0}</BookingNo>"
                            + "<LastName>{1}</LastName>"
                            + "<MemberID></MemberID>"
                            + "</GetPassengers>";
                    soapbody = string.Format(soapbody, args[0], args[1]);
                    username = "NokWin";
                    password = "NokTest2011";
                    xmlns = "http://tempuri.org/";
                    completed = GetPassengers_Completed;
                    ws_endpoint = new Uri("http://dev.nokair.com:8080/NokCheckinService/Service.asmx");
                    break;
                #endregion
                #region RegisterPaymentChannel
                case NokAirServicesMode.RegisterPaymentChannel:
                    action = "http://www.nokair.com/webservices/ReqisterPaymentChannel";
                    soapbody = "<ReqisterPaymentChannel xmlns='http://www.nokair.com/webservices/'><mobileno>{0}</mobileno><payment_type>{1}</payment_type></ReqisterPaymentChannel>";
                    soapbody = string.Format(soapbody, args[0], args[1]);
                    completed = RegisterPaymentChannel_Completed;
                    break;
                #endregion
            }
            string soapMessage =
                "<?xml version='1.0' encoding='utf-8'?>" +
                    "<soap:Envelope xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:xsd='http://www.w3.org/2001/XMLSchema' xmlns:soap='http://schemas.xmlsoap.org/soap/envelope/'>" +
                      "<soap:Header>" +
                        "<AuthenticationHeader xmlns='" + xmlns + "'>" +
                          "<Username>{0}</Username>" +
                          "<Passwd>{1}</Passwd>" +
                        "</AuthenticationHeader>" +
                      "</soap:Header>" +
                      "<soap:Body>{2}</soap:Body>" +
                    "</soap:Envelope>";
            soapMessage = string.Format(soapMessage, username, password, soapbody);
            data = System.Text.Encoding.UTF8.GetBytes(soapMessage);
            #region webservicecontrol

            WebRequest ws_request = HttpWebRequest.Create(ws_endpoint);
            ws_request.ContentType = "text/xml; charset=utf-8";
            ws_request.Headers["SOAPAction"] = action;
            ws_request.Method = "POST";
            #region GetRequestStream
            ws_request.BeginGetRequestStream((GetRequestResult) =>
                {
                    HttpWebRequest request = (HttpWebRequest)GetRequestResult.AsyncState;
                    Stream request_stream = request.EndGetRequestStream(GetRequestResult);

                    //Send SOAP Message
                    request_stream.Write(data, 0, data.Length);
                    request_stream.Flush();
                    request_stream.Close();
                    #region GetResponse
                    request.BeginGetResponse((result) =>
                        {
                            Exception exception = null;
                            Stream response_stream;
                            string soap_response = "";
                            HttpWebRequest GetResponseRequest = (HttpWebRequest)result.AsyncState;
                            try
                            {
                                WebResponse response = GetResponseRequest.EndGetResponse(result);
                                response_stream = response.GetResponseStream();
                                StreamReader reader = new StreamReader(response_stream);
                                soap_response = reader.ReadToEnd();
                                reader.Close();
                                response_stream.Close();
                            }
                            catch (Exception we)
                            {
                                exception = we;
                            }

                            if (completed != null)
                            {
                                completed(this, new RequestCompletedEventArgs(soap_response, exception, GetResponseRequest));
                            }
                        }, request);
                    #endregion
                }, ws_request);
            #endregion
            #endregion
        }

        #region GetAvailableAirports
        public event EventHandler<RequestCompletedEventArgs> GetAvailableAirportCompleted;
        public void GetAvailableAirports()
        {
            CallWebService(NokAirServicesMode.GetAvailableAirports);
        }
        private void GetAvailableAirport_Completed(object sender, WebService.RequestCompletedEventArgs ev)
        {
            XNamespace ns = XNamespace.Get("http://www.nokair.com/webservices/");
            if (ev.exception == null)
            {
                ObservableCollection<NokObjects.AirportItem> airportsItem;
                string response_string = ev.Response;
                airportsItem = new ObservableCollection<NokObjects.AirportItem>();
                //Thread Handling & Parsing SOAP by using LINQ to XML
                XElement e = XElement.Parse(response_string);
                List<XElement> xAirports = e.Descendants(ns + "Airport").ToList();

                foreach (XElement xAirport in xAirports)
                {
                    System.Diagnostics.Debug.WriteLine(xAirport.Name);//AirPort
                    NokObjects.AirportItem airport = new NokObjects.AirportItem()
                    {
                        AirPortName = xAirport.Element(ns + (App.lang == "eng" ? "AirportName" : "AirportNameTH")).Value,
                        AirportCode = xAirport.Element(ns + "AirportCode").Value,
                        AirPortCityCode = xAirport.Element(ns + "CityCode").Value
                    };
                    airportsItem.Add(airport);
                }
                Deployment.Current.Dispatcher.BeginInvoke(() =>
                    Nok_Air.App.ViewModel.AvailableAirportItemsSrc = airportsItem
                );
            }

            if (GetAvailableAirportCompleted != null) GetAvailableAirportCompleted(sender, ev);
        }
        #endregion
        #region GetDestinations
        public event EventHandler<RequestCompletedEventArgs> GetDestinationsCompleted;
        public void GetDestinations(string origin)
        {
            CallWebService(NokAirServicesMode.GetDestinations, origin);
        }
        private void GetDestinations_Completed(object sender, WebService.RequestCompletedEventArgs ev)
        {
            XNamespace ns = XNamespace.Get("http://www.nokair.com/webservices/");
            if (ev.exception == null)
            {
                ObservableCollection<NokObjects.AirportItem> airportsItem;
                string response_string = ev.Response;
                airportsItem = new ObservableCollection<NokObjects.AirportItem>();

                XElement e = XElement.Parse(response_string);
                List<XElement> xAirports = e.Descendants(ns + "Airport").ToList();

                foreach (XElement xAirport in xAirports)
                {
                    System.Diagnostics.Debug.WriteLine(xAirport.Name);//AirPort
                    NokObjects.AirportItem airport = new NokObjects.AirportItem()
                    {
                        AirPortName = xAirport.Element(ns + (App.lang == "eng" ? "AirportName" : "AirportNameTH")).Value,
                        AirportCode = xAirport.Element(ns + "AirportCode").Value,
                        AirPortCityCode = xAirport.Element(ns + "CityCode").Value
                    };
                    airportsItem.Add(airport);
                }
                Deployment.Current.Dispatcher.BeginInvoke(() =>
                    Nok_Air.App.ViewModel.AvailableAirportItemsDest = airportsItem
                );
            }
            if (GetDestinationsCompleted != null) GetDestinationsCompleted(sender, ev);
        }
        #endregion
        #region GetSchedule
        public event EventHandler<RequestCompletedEventArgs> GetScheduleCompleted;
        public void GetSchedule(string _origin, string _destination, DateTime _departureDateTime)
        {
            origin = _origin;
            destination = _destination;
            departureDateTime = _departureDateTime.AddDays(-5);
            departureDay = String.Format("{0:dd}", _departureDateTime);
            departureMonth = String.Format("{0:MM}", _departureDateTime);
            departureYear = String.Format("{0:yyyy}", _departureDateTime);

            CallWebService(NokAirServicesMode.GetSchedule);
        }
        private void GetSchedule_Completed(object sender, WebService.RequestCompletedEventArgs ev)
        {
            XNamespace ns = XNamespace.Get("");
            if (ev.exception == null)
            {
                string soap_response = ev.Response;
                XElement e = XElement.Parse(soap_response);
                List<XElement> xFlights = e.Descendants(ns + "Flight").ToList();

                NokObjects.ScheduleItemViewModel schedule = new NokObjects.ScheduleItemViewModel();
                schedule.Day = departureDateTime;
                schedule.ScheduleItem = new List<NokObjects.ScheduleItemResponse>();

                foreach (XElement xFlight in xFlights)
                {
                    schedule.ScheduleItem.Add(new NokObjects.ScheduleItemResponse()
                    {
                        Departure = xFlight.Element(ns + "Departure").Value,
                        Arrival = xFlight.Element(ns + "Arrival").Value,
                        DepartureTime = xFlight.Element(ns + "DepartureTime").Value,
                        ArrivalTime = xFlight.Element(ns + "ArrivalTime").Value,
                        FlightNumber = xFlight.Element(ns + "FlightNumber").Value
                    });
                }
                Deployment.Current.Dispatcher.BeginInvoke(() =>
                {
                    tmpSchedulItem.Add(schedule);
                });
                if (tmpSchedulItem.Count < 11)
                {
                    departureDateTime = departureDateTime.AddDays(1);
                    CallWebService(NokAirServicesMode.GetSchedule);
                }
            }
            ev.result = tmpSchedulItem;
            if (GetScheduleCompleted != null) GetScheduleCompleted(sender, ev);
        }
        #endregion
        #region GetBookingByBookingNumber
        public event EventHandler<RequestCompletedEventArgs> GetBookingByBookingNumberCompleted;
        public void GetBookingByBookingNumber(string _booking_number, string _lastName)
        {
            CallWebService(NokAirServicesMode.GetBookingByBookingNumber, _booking_number, _lastName);
        }
        private void GetBookingByBookingNumber_Completed(object sender, WebService.RequestCompletedEventArgs ev)
        {
            XNamespace ns = XNamespace.Get("");
            if (ev.exception == null)
            {
                XElement e = XElement.Parse(ev.Response);
                XElement xBooking = e.Descendants(ns + "BOOKING").First();
                NokObjects.BookingItemViewModel bookingitems = new NokObjects.BookingItemViewModel();

                bookingitems.BookNo = xBooking.Element(ns + "BookNo").Value;
                bookingitems.NoOfSeats = xBooking.Element(ns + "NoOfSeats").Value;
                bookingitems.TotalPayment = xBooking.Element(ns + "SUMMARY").Element(ns + "TotalPayment").Value;
                bookingitems.PassengerItem = new List<BookingItemPassengers>();
                foreach (XElement xPassenger in xBooking.Descendants("PASSENGER"))
                {
                    bookingitems.PassengerItem.Add(new BookingItemPassengers()
                    {
                        PassCode = xPassenger.Element(ns + "PassCode").Value,
                        PassengerName = xPassenger.Element(ns + "PassengerName").Value,
                        PassengerNo = xPassenger.Element(ns + "PassengerNo").Value
                    });
                }
                bookingitems.SegmentItem = new List<BookingItemSegments>();
                foreach (XElement xSegment in xBooking.Descendants("SEGMENT"))
                {
                    bookingitems.SegmentItem.Add(new BookingItemSegments()
                    {
                        RouteNo = xSegment.Element(ns + "RouteNo").Value,
                        ArrivalAirportName = xSegment.Element(ns + "ArrivalAirportName").Value,
                        ArrivalTime = xSegment.Element(ns + "ArrivalTime").Value,
                        DepartureAirportName = xSegment.Element(ns + "DepartureAirportName").Value,
                        DepartureTime = xSegment.Element(ns + "DepartureTime").Value,
                        FlightDate = xSegment.Element(ns + "FlightDate").Value,
                        FlightNumber = xSegment.Element(ns + "FlightNumber").Value,
                        SellingClsCode = xSegment.Element(ns + "SellingClsCode").Value,
                    });
                }
                bookingitems.PAYMENTS = new PAYMENT();
                foreach (XElement xPayment in xBooking.Descendants("PAYMENT"))
                {
                    bookingitems.PAYMENTS = new PAYMENT()
                    {
                        PaymentNo = xPayment.Element(ns + "PaymentNo").Value,
                        PaymentAmount = xPayment.Element(ns + "PaymentAmount").Value,
                        PaymentDate = xPayment.Element(ns + "PaymentDate").Value,
                        PaymentDateTime = xPayment.Element(ns + "PaymentDateTime").Value
                    };
                }
                Deployment.Current.Dispatcher.BeginInvoke(() =>
                    Nok_Air.App.ViewModel.BookingItems = bookingitems
                );
            }
            if (GetBookingByBookingNumberCompleted != null) GetBookingByBookingNumberCompleted(sender, ev);
        }
        #endregion
        #region GetAvailability
        public event EventHandler<RequestCompletedEventArgs> GetAvailabilityCompleted;
        public void GetAvailability(string _origin, string _destination, DateTime _departureDateTime, DateTime _returnDateTime, string _roundtripFlag, string _numseat)
        {
            origin = _origin;
            destination = _destination;
            departureDateTime = _departureDateTime;
            returnDateTime = _returnDateTime;
            roundtripFlag = _roundtripFlag;
            numseat = _numseat;
            CallWebService(NokAirServicesMode.GetAvailability);
        }
        private void GetAvailability_Completed(object sender, WebService.RequestCompletedEventArgs ev)
        {
            XNamespace ns = XNamespace.Get("");
            if (ev.exception == null)
            {
                XElement e = XElement.Parse(ev.Response);

                List<XElement> xOptions = e.Descendants(ns + "OriginDestinationOption").ToList();

                tmpFlightSegments = new ObservableCollection<AvailabilityItemViewModel>();
                AvailabilityItemViewModel availableItem = new AvailabilityItemViewModel();

                availableItem.Date = departureDateTime;
                availableItem.FlightSegmentItem = new List<FlightSegmentItemViewModel>();
                bool isSpiltReturnFlight = false;

                foreach (XElement xOption in xOptions)
                {
                    foreach (XElement xFlightSegment in xOption.Elements())
                    {
                        System.Diagnostics.Debug.WriteLine(xFlightSegment.Name); //FlightSegment
                        #region Initialize flightsegment
                        FlightSegmentItemViewModel flightSegmentItem = new FlightSegmentItemViewModel();

                        // split round trip
                        if (origin != xFlightSegment.Element(ns + "DepartureAirport").Value && !isSpiltReturnFlight)
                        {
                            tmpFlightSegments.Add(availableItem);
                            availableItem = new AvailabilityItemViewModel();
                            availableItem.Date = returnDateTime;
                            availableItem.FlightSegmentItem = new List<FlightSegmentItemViewModel>();
                            isSpiltReturnFlight = true;
                        }
                        flightSegmentItem.DepartureAirport = xFlightSegment.Element(ns + "DepartureAirport").Value;
                        flightSegmentItem.ArrivalAirport = xFlightSegment.Element(ns + "ArrivalAirport").Value;
                        flightSegmentItem.FlightNumber = xFlightSegment.Element(ns + "FlightNumber").Value;
                        flightSegmentItem.BoardDate = xFlightSegment.Element(ns + "BoardDate").Value;
                        flightSegmentItem.ArrivalTime = xFlightSegment.Element(ns + "ArrivalTime").Value;
                        flightSegmentItem.DepartureTime = xFlightSegment.Element(ns + "DepartureTime").Value;
                        flightSegmentItem.TotalJourneyTime = xFlightSegment.Element(ns + "TotalJourneyTime").Value;
                        flightSegmentItem.ClassFlexi = new FSegSellingClass();
                        flightSegmentItem.ClassEconomy = new FSegSellingClass();
                        flightSegmentItem.ClassNokPlus = new FSegSellingClass();

                        List<XElement> xSellingClasses = xFlightSegment.Descendants("SellingClass").ToList();
                        #endregion
                        foreach (XElement xSellingClass in xFlightSegment.Descendants("SellingClass"))
                        {
                            ///create sellingClass instance WITHOUT ClassName which will be added later according to its class
                            FSegSellingClass sellingClass = new FSegSellingClass()
                            {
                                GroupRadioBT = flightSegmentItem.DepartureAirport,
                                ClassCode = xSellingClass.Element(ns + "ClassCode").Value,
                                SeatCount = xSellingClass.Element(ns + "SeatCount").Value,
                                FareCode = xSellingClass.Element(ns + "FareCode").Value,
                                FareValue = xSellingClass.Element(ns + "FareValue").Value,
                                TaxValue = xSellingClass.Element(ns + "TaxValue").Value,
                                RefundableFlag = xSellingClass.Element(ns + "RefundableFlag").Value,
                                FloatingFareFlag = xSellingClass.Element(ns + "FloatingFareFlag").Value,
                                FloatingBaseClass = xSellingClass.Element(ns + "FloatingBaseClass").Value,
                                Cabin = xSellingClass.Element(ns + "Cabin").Value
                            };

                            string classcode = xSellingClass.Element(ns + "ClassCode").Value;
                            switch (classcode)
                            {
                                case "X":
                                case "C":
                                case "D":
                                case "J":
                                    sellingClass.ClassName = App.ViewModel.NokPlus;
                                    if (flightSegmentItem.ClassNokPlus.FareValue == null || (double.Parse(flightSegmentItem.ClassNokPlus.FareValue) > double.Parse(sellingClass.FareValue)))
                                        flightSegmentItem.ClassNokPlus = sellingClass;
                                    break;
                                case "Y":
                                case "Q":
                                case "H":
                                    sellingClass.ClassName = App.ViewModel.NokFlexi;
                                    if (flightSegmentItem.ClassFlexi.FareValue == null || (double.Parse(flightSegmentItem.ClassFlexi.FareValue) > double.Parse(sellingClass.FareValue)))
                                        flightSegmentItem.ClassFlexi = sellingClass;
                                    break;
                                default:
                                    sellingClass.ClassName = App.ViewModel.NokEco;
                                    if (flightSegmentItem.ClassEconomy.FareValue == null || (double.Parse(flightSegmentItem.ClassEconomy.FareValue) > double.Parse(sellingClass.FareValue)))
                                        flightSegmentItem.ClassEconomy = sellingClass;
                                    break;
                            }
                        }
                        availableItem.FlightSegmentItem.Add(flightSegmentItem);
                    }
                }
                Deployment.Current.Dispatcher.BeginInvoke(() =>
                {
                    tmpFlightSegments.Add(availableItem);
                    Nok_Air.App.ViewModel.AvailabilityItems = tmpFlightSegments;
                    if (GetAvailabilityCompleted != null) GetAvailabilityCompleted(sender, ev);
                });
            }
        }
        #endregion
        #region GetSeats
        public event EventHandler<RequestCompletedEventArgs> GetSeatsCompleted;
        public void GetSeats(string FlightNo, string FlightDate, string Bookingno, string ClassCode)
        {
            CallWebService(NokAirServicesMode.GetSeats, FlightNo, FlightDate, Bookingno, ClassCode);
        }
        private void GetSeats_Completed(object sender, WebService.RequestCompletedEventArgs ev)
        {
            XNamespace ns = "http://tempuri.org/";
            if (ev.exception == null)
            {
                XElement e = XElement.Parse(ev.Response);
                IEnumerable<XElement> xSeatsResults = e.Descendants(ns + "GetSeatsResult").Elements();

                ns = "";
                App.ViewModel.GetSeatsResult = new NokObjects.GetSeatsResultViewModel();
                foreach (XElement xSeatsResult in xSeatsResults)
                {
                    System.Diagnostics.Debug.WriteLine(xSeatsResult.Name);
                    App.ViewModel.GetSeatsResult.Code = xSeatsResult.Element(ns + "Code").Value;
                    App.ViewModel.GetSeatsResult.ResponseDesc = xSeatsResult.Element(ns + "ResponseDesc").Value;
                    foreach (XElement xFlight in xSeatsResult.Descendants("Flight"))
                    {
                        App.ViewModel.GetSeatsResult.Flight = new FlightGetPassengersResult()
                        {
                            FlightNo = xFlight.Element(ns + "No").Value,
                            FlightDate = xFlight.Element(ns + "Date").Value,
                        };
                    }
                    List<SeatGetSeatsResult> _tmpSeatGetSeatsResult = new List<SeatGetSeatsResult>();
                    foreach (XElement xSeat in xSeatsResult.Descendants("Seat"))
                    {
                        string _no = xSeat.Element(ns + "No").Value;
                        string _charNo = _no.Substring((_no.Length - 1)).ToUpper();
                        string _numbericNo = _no.Substring(0, (_no.Length - 1));
                        _tmpSeatGetSeatsResult.Add(new SeatGetSeatsResult()
                        {
                            No = _no,
                            Status = xSeat.Element(ns + "Status").Value,
                            Type = xSeat.Element(ns + "Type").Value,
                            SeatZone = xSeat.Element(ns + "SeatZone").Value,
                            NumbericNo = int.Parse(_numbericNo),
                            CharNo = _charNo
                        });
                    }
                    var _tmpListSeatGetSeatsResult = _tmpSeatGetSeatsResult
                         .GroupBy(u => u.NumbericNo)
                         .Select(grp => grp.ToList())
                         .ToList();

                    App.ViewModel.GetSeatsResult.SeatGroup = new List<SeatGroupGetSeatsResult>();

                    foreach (List<SeatGetSeatsResult> _seatList in _tmpListSeatGetSeatsResult)
                    {
                        SeatGroupGetSeatsResult _seatGroup = new SeatGroupGetSeatsResult();
                        _seatGroup.RightSide = new List<SeatGetSeatsResult>();
                        _seatGroup.LeftSide = new List<SeatGetSeatsResult>();
                        string _charNo = "@"; // @ => index = 64 in ASCII map, A => index = 65.
                        foreach (SeatGetSeatsResult _seat in _seatList)
                        {
                            _seatGroup.Row = _seat.NumbericNo.ToString();
                            string nextChar = string.Format("{0}", (char)(_charNo[0] + 1));
                            if (_seat.CharNo == nextChar)
                            {
                                _seatGroup.RightSide.Add(_seat);
                            }
                            else
                            {
                                _seatGroup.LeftSide.Add(_seat);
                            }
                            _charNo = nextChar;// _seat.CharNo;
                        }
                        App.ViewModel.GetSeatsResult.SeatGroup.Add(_seatGroup);
                    }
                }
            }
            if (GetSeatsCompleted != null) GetSeatsCompleted(sender, ev);
        }
        #endregion
        #region GetFees
        public event EventHandler<RequestCompletedEventArgs> GetFeesCompleted;
        public void GetFees()
        {
            CallWebService(NokAirServicesMode.GetFees);
            Nok_Air.App.ViewModel.FeeItem = new ObservableCollection<NokAirWS.Fee>();
        }
        private void GetFees_Completed(object sender, WebService.RequestCompletedEventArgs ev)
        {
            if(ev.exception == null)
            {
                XElement xResult = XElement.Parse(ev.Response);
                XElement xFees = xResult.Descendants(XNamespace.Get("http://www.nokair.com/webservices/") + "GetFeesResult").First();
                XmlRootAttribute xRoot = new XmlRootAttribute("GetFeesResult") { Namespace = "http://www.nokair.com/webservices/" };
                Nok_Air.App.ViewModel.FeeItem = Deserialize<ObservableCollection<NokAirWS.Fee>>(xFees, xRoot);
            }
            if (GetAvailabilityCompleted != null) GetAvailabilityCompleted(sender, ev);
        }
        #endregion
        #region SubmitBookingV2
        public event EventHandler<RequestCompletedEventArgs> SubmitBookingV2Completed;
        public void SubmitBookingV2(string _PricingId, string _FlightsXMLString, string _PassengerXMLString, string _PaymentType, string _Amount, string _ContactXMLString, string _RegisterId, string _lastnamePar)
        {
            this.lastnamePar = _lastnamePar;
            CallWebService(NokAirServicesMode.SubmitBookingV2, _PricingId, _FlightsXMLString, _PassengerXMLString, _PaymentType, _Amount, _ContactXMLString, _RegisterId);
            Nok_Air.App.ViewModel.SubmitBookingV2Result = "";
        }
        private void SubmitBookingV2_Completed(object sender, WebService.RequestCompletedEventArgs ev)
        {
            if (ev.exception == null)
            {
                XElement e = XElement.Parse(ev.Response);
                XElement xResult = e.Descendants(XName.Get("SubmitBookingV2Result", "http://www.nokair.com/webservices/")).First();

                Nok_Air.App.ViewModel.SubmitBookingV2Result = xResult.Value;
                GetSubmitBookingStatus(Nok_Air.App.ViewModel.SubmitBookingV2Result, this.lastnamePar);
            }
            if (SubmitBookingV2Completed != null) SubmitBookingV2Completed(sender, ev);
        }
        #endregion
        #region CheckIn
        public event EventHandler<RequestCompletedEventArgs> CheckInCompleted;
        public void CheckIn(string passengerXML, int _indexFlight)
        {
            indexFlight = _indexFlight;
            CallWebService(NokAirServicesMode.CheckIn, passengerXML);
        }
        private void CheckIn_Completed(object sender, WebService.RequestCompletedEventArgs ev)
        {
            XNamespace ns = "http://tempuri.org/";
            if(ev.exception == null)
            {
                XElement e = XElement.Parse(ev.Response);
                IEnumerable<XElement> xResults = e.Descendants(ns + "CheckInResult");

                ns = "";
                foreach (XElement xResult in xResults.Elements())
                {
                    System.Diagnostics.Debug.WriteLine(xResult.Name);
                    if (xResult.Element(ns + "Code").Value != "0000")
                    {
                        MessageBox.Show(xResult.Element(ns + "ResponseDesc").Value);
                    }
                    else
                    {
                        MessageBox.Show(App.ViewModel.BoardingPassAlertMsg);
                        App.ViewModel.GetPassengersResult.Code = xResult.Element(ns + "Code").Value;
                        foreach (XElement xFlight in xResult.Descendants("Flight"))
                        {
                            List<PassengerGetPassengersResult> _tmpPassengers = new List<PassengerGetPassengersResult>();
                            foreach (XElement xPassengers in xFlight.Elements("Passengers"))
                            {
                                foreach (XElement xPassenger in xPassengers.Descendants("Passenger"))
                                {
                                    // if already checkin
                                    if (xPassenger.Element(ns + "CheckInStatus").Value.ToUpper() == "Y")
                                    {
                                        var _passengers = from p in App.ViewModel.GetPassengersResult.Flights[indexFlight].Passengers
                                                          where p.Name.Equals(xPassenger.Element(ns + "Name").Value)
                                                          && p.BookingNo.Equals(xPassenger.Element(ns + "BookingNo").Value)
                                                          && p.SeatNo.Equals(xPassenger.Element(ns + "SeatNo").Value)
                                                          select p;

                                        foreach (var _passenger in _passengers)
                                        {
                                            _passenger.RowID = xPassenger.Element(ns + "RowID").Value;
                                            _passenger.BookingNo = xPassenger.Element(ns + "BookingNo").Value;
                                            _passenger.PNRNo = xPassenger.Element(ns + "PNRNo").Value;
                                            _passenger.Name = xPassenger.Element(ns + "Name").Value;
                                            _passenger.SeatNo = xPassenger.Element(ns + "SeatNo").Value;
                                            _passenger.ClassCode = xPassenger.Element(ns + "ClassCode").Value;
                                            _passenger.MemberID = xPassenger.Element(ns + "MemberID").Value;
                                            _passenger.CheckInStatus = xPassenger.Element(ns + "CheckInStatus").Value;
                                            _passenger.Meal = xPassenger.Element(ns + "Meal").Value;
                                            _passenger.CheckInSeq = xPassenger.Element(ns + "CheckInSeq").Value;
                                            _passenger.CheckInTime = xPassenger.Element(ns + "CheckInTime").Value;
                                            _passenger.BoardingTime = xPassenger.Element(ns + "BoardingTime").Value;
                                            _passenger.Barcode = xPassenger.Element(ns + "Barcode").Value;
                                        }
                                    }
                                }
                            }

                            App.ViewModel.GetPassengersResult.Flights[indexFlight].FlightNo = xFlight.Element(ns + "FlightNo").Value;
                            App.ViewModel.GetPassengersResult.Flights[indexFlight].FlightDate = xFlight.Element(ns + "FlightDate").Value;
                            App.ViewModel.GetPassengersResult.Flights[indexFlight].DepartFrom = xFlight.Element(ns + "DepartFrom").Value;
                            App.ViewModel.GetPassengersResult.Flights[indexFlight].LDepartFrom = xFlight.Element(ns + "LDepartFrom").Value;
                            App.ViewModel.GetPassengersResult.Flights[indexFlight].DepartTime = xFlight.Element(ns + "DepartTime").Value;
                            App.ViewModel.GetPassengersResult.Flights[indexFlight].ArriveTo = xFlight.Element(ns + "ArriveTo").Value;
                            App.ViewModel.GetPassengersResult.Flights[indexFlight].LArriveTo = xFlight.Element(ns + "LArriveTo").Value;
                            App.ViewModel.GetPassengersResult.Flights[indexFlight].ArrivalTime = xFlight.Element(ns + "ArrivalTime").Value;
                            App.ViewModel.GetPassengersResult.Flights[indexFlight].AircraftType = xFlight.Element(ns + "AircraftType").Value;
                            App.ViewModel.GetPassengersResult.Flights[indexFlight].GateNo = xFlight.Element(ns + "GateNo").Value;
                        }
                    }
                }
            }
            if (CheckInCompleted != null) CheckInCompleted(sender, ev);
        }
        /* older function removed. if neccessary restore to CHANGESET 75129 */
        #endregion
        #region GetSubmitBookingStatus
        public event EventHandler<RequestCompletedEventArgs> GetSubmitBookingStatusCompleted;
        public void GetSubmitBookingStatus(string _SubmitID, string _lastnamePar)
        {
            this.lastnamePar = _lastnamePar;
            SubmitID = _SubmitID;
            CallWebService(NokAirServicesMode.GetSubmitBookingStatus, _SubmitID);
        }
        private void GetSubmitBookingStatus_Completed(object sender, WebService.RequestCompletedEventArgs ev)
        {
            XNamespace ns = "";
            if (ev.exception == null)
            {
                XElement e = XElement.Parse(ev.Response);
                XElement xResult = e.Descendants(ns + "SubmitBookingStatus").First();

                if (xResult.Element(ns + "Completed").Value.ToLower() == "false")
                {
                    CallWebService(NokAirServicesMode.GetSubmitBookingStatus, SubmitID);
                }
                else
                {
                    XmlRootAttribute xRoot = new XmlRootAttribute() { Namespace = "" };
                    App.ViewModel.SubmitBookingStatus = Deserialize<SubmitBookingStatus>(xResult, xRoot);
                    GetBookingByBookingNumberCompleted += (ss, ee) =>
                        {
                            if (GetSubmitBookingStatusCompleted != null) GetSubmitBookingStatusCompleted(sender, ev);
                        };
                    GetBookingByBookingNumber(App.ViewModel.SubmitBookingStatus.BookNo, this.lastnamePar);
                }
            }
        }
        #endregion
        #region GetPassengers
        public event EventHandler<RequestCompletedEventArgs> GetPassengersCompleted;
        public void GetPassengers(string _BookingNo, string _LastName)
        {
            CallWebService(NokAirServicesMode.GetPassengers, _BookingNo, _LastName);
        }
        private void GetPassengers_Completed(object sender, WebService.RequestCompletedEventArgs ev)
        {
            if(ev.exception == null)
            {
                XNamespace ns = "http://tempuri.org/";
                XElement e = XElement.Parse(ev.Response);

                ns = "";
                XElement xResponse = e.Descendants(ns + "Response").First();
                XmlRootAttribute xroot = new XmlRootAttribute("Response") { Namespace = "" };

                NokObjects.GetPassengersResultViewModel getPassengersResult = Deserialize<NokObjects.GetPassengersResultViewModel>(xResponse, xroot);

                if (getPassengersResult.Code != "0000")
                {
                    ev.exception = new Exception(getPassengersResult.ResponseDesc);
                }
                else
                {
                    getPassengersResult.Flights = new List<FlightGetPassengersResult>();

                    foreach (XElement xFlight in xResponse.Descendants("Flight"))
                    {
                        xroot.ElementName = "Flight";
                        var flight = Deserialize<FlightGetPassengersResult>(xFlight, xroot);

                        xroot.ElementName = "Passengers";
                        var passengers = Deserialize<List<PassengerGetPassengersResult>>(xFlight.Element(ns + "Passengers"), xroot);

                        flight.Passengers = passengers;
                        getPassengersResult.Flights.Add(flight);
                    }

                    Deployment.Current.Dispatcher.BeginInvoke(() =>
                        App.ViewModel.GetPassengersResult = getPassengersResult
                    );
                }
            }
            if (GetPassengersCompleted != null) GetPassengersCompleted(sender, ev);
        }
        /* removed OLDER function from CHANGESET 75129*/
        #endregion
        #region PricingV2
        public event EventHandler<RequestCompletedEventArgs> PricingCompleted;
        public void PricingV2(string pricingV2XMLString)
        {
            Nok_Air.App.ViewModel.PricingV2Items = new NokObjects.PricingV2ItemViewModel();
            CallWebService(NokAirServicesMode.PricingV2, pricingV2XMLString);
        }
        private void PricingV2_Completed(object sender, WebService.RequestCompletedEventArgs ev)
        {
            if(ev.exception == null)
            {
                XNamespace ns = "";
                XElement e = XElement.Parse(ev.Response);
                var e1 = e.Elements();
                XElement xSummary = e.Descendants(ns + "PriceSummary").First();
                System.Diagnostics.Debug.WriteLine(xSummary.Name);//PriceSummary

                XmlRootAttribute xRoot = new XmlRootAttribute("PriceSummary") { Namespace = ns.NamespaceName };
                NokObjects.PricingV2ItemViewModel summary = Deserialize<PricingV2ItemViewModel>(xSummary, xRoot);

                XElement xFee = xSummary.Element(ns + "FeeCodes").Element(ns + "Fee");
                xRoot.ElementName = "Fee";
                summary.FeeCodes = Deserialize<Fee>(xFee, xRoot);

                Deployment.Current.Dispatcher.BeginInvoke(() =>
                {
                    Nok_Air.App.ViewModel.PricingV2Items = summary;
                });
            }
            if (PricingCompleted != null) PricingCompleted(sender, ev);
        }
        #endregion
        #region GetInventoryDate
        public event EventHandler<RequestCompletedEventArgs> GetInventoryDateCompleted;
        public void GetInventoryDate()
        {
            CallWebService(NokAirServicesMode.GetInventoryDate);
            Nok_Air.App.ViewModel.FeeItem = new ObservableCollection<NokAirWS.Fee>();
        }
        private void GetInventoryDate_Completed(object sender, WebService.RequestCompletedEventArgs ev)
        {
            if(ev.exception == null)
            {
                XElement e = XElement.Parse(ev.Response);
                //List<XElement> res = e.Descendants(XName.Get("GetInventoryDateResult")).ToList();
                XElement res = e.Descendants(XName.Get("GetInventoryDateResult", "http://www.nokair.com/webservices/")).ToList()[0];
                string datetimeString = res.Value;
            }
            if (GetInventoryDateCompleted != null) GetInventoryDateCompleted(sender, ev);
        }
        #endregion
        #region RegisterPaymentChannel
        public event EventHandler<RequestCompletedEventArgs> RegisterPaymentChannelCompleted;
        public void RegisterPaymentChannel(string _mobileno, string _paymentType)
        {
            if (App.checkConnection())
            {
                CallWebService(NokAirServicesMode.RegisterPaymentChannel, _mobileno, _paymentType);
                Nok_Air.App.ViewModel.ReqisterPaymentChannelResult = new ObservableCollection<string>();
            }
        }
        private void RegisterPaymentChannel_Completed(object sender, WebService.RequestCompletedEventArgs ev)
        {
            XNamespace ns = "http://www.nokair.com/webservices/";
            if (ev.exception == null)
            {
                XElement e = XElement.Parse(ev.Response);
                var xResult = e.Descendants(ns + "ReqisterPaymentChannelResult").First();
                System.Diagnostics.Debug.WriteLine(xResult.Name);//ReqisterPaymentChannelResult

                Deployment.Current.Dispatcher.BeginInvoke(() =>
                {
                    Nok_Air.App.ViewModel.ReqisterPaymentChannelResult.Add(xResult.Element(ns + "Code").Value);
                    Nok_Air.App.ViewModel.ReqisterPaymentChannelResult.Add(xResult.Element(ns + "Description").Value);
                });
            }
            if (RegisterPaymentChannelCompleted != null) RegisterPaymentChannelCompleted(sender, ev);
        }
        #endregion
    }

    public class RequestCompletedEventArgs : AsyncCompletedEventArgs
    {
        public string Response
        {
            get;
            private set;
        }
        public Exception exception;
        public object result;

        public RequestCompletedEventArgs(string response_string, Exception ex, Object userState)
            : base(ex, false, userState)
        {
            Response = response_string;
            exception = ex;
            result = userState;
        }
    }
}